import CCLog from "../CCLog";
import { AUDIOS_PATH } from "../Common/AudioConfig";
import { BLOCK_COLLECT_SPEED, CUSTOM_EVENT_NAME, GUIDE_BLOCK_ZINDEX, NODE_POOL_NAME, TOUCHER_COLLIDER_TAG } from "../Common/Constant";
import getEventEmiter from "../Libraries/EventEmitter";
import NodePool from "../Libraries/NodePool";
import AudioTool from "../System/AudioSystem";
import CatcherController from "./CatcherController";
import GamePlayController from "./GamePlayController";
import PropAreaController from "./PropAreaController";
import SingleCatcherController from "./SingleCatcherController";
import ToucherController from "./ToucherController";

const { ccclass, property } = cc._decorator;
const indexOffset: number = 1000;
const clickOriginScale: number = 1;
const clickScaleAddition: number = 0.1;
const clickScaleTime: number = 0.05;

@ccclass
export default class SingleBlockController extends cc.Component {
    @property(cc.Node)
    public nodeGuideHand: cc.Node = null;

    @property(cc.Sprite)
    public blockSkin: cc.Sprite = null;

    @property(cc.BoxCollider)
    public collider: cc.BoxCollider = null;

    public stayCatcher: SingleCatcherController = null; //捕获catcher
    public isMoving: boolean = false;
    public isEliminating: boolean = false;//正在消除
    public layerNumber: number;
    public indexNumber: number;

    private _originParent: cc.Node;
    private _originZindex: number;
    private _originScale: number;
    private _originPosition: cc.Vec3;
    private _collectd: boolean = false;
    private _touched: boolean = false;
    private _blockCoverd: cc.Node[] = [];
    private _clickTween: cc.Tween;
    private _isGuide: boolean = false;

    private _available: boolean = true;
    public get available(): boolean {
        return this._available;
    }
    public set available(v: boolean) {
        this._available = v;
        this.blockSkin.node.color = v ? cc.color(255, 255, 255) : cc.color(120, 120, 120);
    }

    public onLoad() {
        getEventEmiter().on(CUSTOM_EVENT_NAME.onSceneChanged, this.__onSceneChanged, this);
    }

    public onDisable() {
        getEventEmiter().off(CUSTOM_EVENT_NAME.onSceneChanged, this.__onSceneChanged, this);
    }

    public start() {
        this.nodeGuideHand.active = false;
    }

    public onCollisionEnter(other: cc.BoxCollider, self: cc.BoxCollider): void {
        if (other.tag === TOUCHER_COLLIDER_TAG) {
            if (!this.available) return;
            this.__onTouchEnter();
            return;
        }
        if (other.tag < this.collider.tag) return;
        this._blockCoverd.push(other.node);
        this.available = false;
    }

    public onCollisionExit(other: cc.BoxCollider, self: cc.BoxCollider): void {
        if (other.tag === TOUCHER_COLLIDER_TAG) {
            if (!this.available) return;
            this.__onTouchOut();
            return;
        }
        if (other.tag < self.tag) return;
        let index = this._blockCoverd.indexOf(other.node);
        if (index === -1) return;
        this._blockCoverd.splice(index, 1);
        if (this._blockCoverd.length === 0) this.available = true;
    }

    public init(skin: cc.SpriteFrame, zIndex: number, tag: number, layerNumber: number, indexNumber: number): void {
        this._collectd = false;
        this._blockCoverd.length = 0;
        this._isGuide = false;
        this.available = true;
        this.blockSkin.spriteFrame = skin;
        this.node.zIndex = zIndex;
        //this.node.scale = 1.1;
        this._originParent = this.node.parent;

        this._originZindex = zIndex;
        this._originPosition = this.node.position;
        this.stayCatcher = null;
        this.isEliminating = false;
        this.isMoving = false;
        this.collider.tag = tag;
        this.collider.enabled = true;
        this.layerNumber = layerNumber;
        this.indexNumber = indexNumber;

        //cc.log("this._originParent===",this._originParent);
    }
    public initScale(): void {
     
        this.node.scale = 1.1;
        this._originScale = this.node.scale ;
    }

   
    public collect(): boolean {
        if (this._collectd) return false;
        
        CCLog.log("接受块")
        let catched: boolean = CatcherController.I.catchOneBlock(this);
        if (!catched) return;
        PropAreaController.I.hideTip();
        GamePlayController.I.updateBlockLeft(this);
        this._collectd = true;
        this.collider.enabled = false;
        this.nodeGuideHand.active = false;
        return true;
    }

    public recover(): void {
        GamePlayController.I.setIsReCall(true);
        this.available = true;
        this.stayCatcher.discardBlock();
        this.stayCatcher = null;
       
        let posTo: cc.Vec3 = this.node.parent.convertToNodeSpaceAR(this._originParent.convertToWorldSpaceAR(this._originPosition));
        cc.tween(this.node)
            .to(
                posTo.sub(this.node.position).mag() / BLOCK_COLLECT_SPEED
                , { position: posTo }
                , { easing: cc.easing.quadOut }
            )
            .call(() => {
                this.node.setParent(this._originParent);
                this.node.setPosition(this._originPosition);
                this.node.scale = this._originScale;
                this.node.zIndex = this._originZindex;
                this.collider.enabled = true;
                this._collectd = false;
                GamePlayController.I.setIsReCall(false);
            })
            .start();
        CatcherController.I.resetPosAfterRecall();
    }

    /**
     * 消除时调用
     */
    public eliminateSelf(): Promise<any> {
        this.isEliminating = true;
        return new Promise((resolve: Function, reject: Function) => {
            cc.tween(this.node)
                .to(0.1, { scale: this.node.scale * 1.1 })
                .to(0.15, { scale: 0 })
                .call(() => {
                    if (this.stayCatcher) {
                        this.stayCatcher.afterEliminate();
                    }
                    
                    NodePool.putItem(NODE_POOL_NAME.singleBlock, this.node);
                    GamePlayController.I.subBlockNum();
                    resolve();
                })
                .start();
        });
    }

    /**
     * 被接收后执行
     */
    public onCatched(): void {
        this.isMoving = false;
        this.node.scale = 1;
        CatcherController.I.checkEliminate(this.blockSkin.spriteFrame);
    }

    /**
     * 移动到layerMap
     */
    public moveToLayerMap(parent?:cc.Node): void {
        const layerMap = parent == undefined ? GamePlayController.I.nodeLayerMap : parent;
        let mapPosFrom: cc.Vec2 = layerMap.convertToNodeSpaceAR(this.node.convertToWorldSpaceAR(cc.v2(0, 0)));
        this.node.setParent(layerMap);
        this.node.setPosition(mapPosFrom);
        this.node.zIndex = GUIDE_BLOCK_ZINDEX;
        this._isGuide = true;
        this.nodeGuideHand.active = true;
    }


    private __onTouchEnter(): void {
        AudioTool.play(AUDIOS_PATH.block_click);
     
        this._touched = true;
        this.node.zIndex += indexOffset;
        ToucherController.I.matchTarget(this);
        if (this._clickTween) this._clickTween.stop();
        this._clickTween = cc.tween(this.node)
            .to(
                ((1 + clickScaleAddition) - this.node.scale) / clickScaleAddition * clickScaleTime,
                { scale: this._originScale * (1 + clickScaleAddition) }
            )
            .start();
    }

    private __onTouchOut(): void {
        if (!this._touched) return;
        this._touched = false;
        ToucherController.I.releaseTarget();
        if (this._clickTween) this._clickTween.stop();
        this._clickTween = cc.tween(this.node)
            .to(
                (this.node.scale - this._originScale) / clickScaleAddition * clickScaleTime
                , { scale: this._originScale }
            )
            .start();
        if (this.isMoving) return;
        this.node.zIndex -= indexOffset;
    }

    private __onSceneChanged() {
        if (this._collectd) this.node.active = false;
    }
}
